import numpy as np

out_file = "mbv2_para.h"
bita, sym_bita = 8,  "BIT_ACTV"
bitw, sym_bitw = 8,  "BIT_WGHT"
bitb, sym_bitb = 24, "BIT_BIAS"
bitm, sym_bitm = 24, "BIT_MULT"

prefixs = [
"conv0",
"b1n1_c1", "b1n1_c2", "b1n1_c3",
"b2n1_c1", "b2n1_c2", "b2n1_c3", "b2n2_c1", "b2n2_c2", "b2n2_c3",
"b3n1_c1", "b3n1_c2", "b3n1_c3", "b3n2_c1", "b3n2_c2", "b3n2_c3", "b3n3_c1", "b3n3_c2", "b3n3_c3",
"b4n1_c1", "b4n1_c2", "b4n1_c3", "b4n2_c1", "b4n2_c2", "b4n2_c3", "b4n3_c1", "b4n3_c2", "b4n3_c3", "b4n4_c1", "b4n4_c2", "b4n4_c3",
"b5n1_c1", "b5n1_c2", "b5n1_c3", "b5n2_c1", "b5n2_c2", "b5n2_c3", "b5n3_c1", "b5n3_c2", "b5n3_c3",
"b6n1_c1", "b6n1_c2", "b6n1_c3", "b6n2_c1", "b6n2_c2", "b6n2_c3", "b6n3_c1", "b6n3_c2", "b6n3_c3",
"b7n1_c1", "b7n1_c2", "b7n1_c3",
"conv8", "conv9"]

parallel=[
(3,32,4),
(8,16,4),	(32,4),	(4,16,2),
(8,16,8),	(24,2),	(6,8,1),	(6,12,3),	(36,3),	(6,12,1),
(6,12,4),	(8,1),	(3,8,1),	(4,8,1),	(12,1),	(4,8,1),	(4,8,1),	(12,1),	(4,8,1),
(4,8,1),	(3,1),	(4,4,1),	(4,8,1),	(6,1),	(4,8,1),	(4,8,1),	(6,1),	(4,8,1),	(4,8,1),	(6,1),	(4,8,1),
(4,8,1),	(6,1),	(6,8,1),	(6,12,1),	(8,1),	(6,12,1),	(6,12,1),	(8,1),	(6,12,1),
(6,12,1),	(2,1),	(4,8,1),	(8,6,1),	(3,1),	(6,8,1),	(8,6,1),	(3,1),	(6,8,1),
(8,6,1),	(3,1),	(6,16,1),
(8,16,1),
(1,1,1),
]

parallel_dwc_r=[
(3,8,4),
(8,16,4),	(32,4),		(4,16,2),
(8,16,8),	(96,2,4,0),	(6,8,1),	(6,12,3),	(36,3),	(6,12,1),
(6,12,4),	(36,1,4,0),	(3,8,1),	(4,8,1),	(12,1),	(4,8,1),	(4,8,1),	(12,1),	(4,8,1),
(4,8,1),	(12,1,4,0),	(4,4,1),	(4,8,1),	(6,1),	(4,8,1),	(4,8,1),	(6,1),	(4,8,1),	(4,8,1),	(6,1),	(4,8,1),
(4,8,1),	(6,1),		(6,8,1),	(6,12,1),	(8,1),	(6,12,1),	(6,12,1),	(8,1),	(6,12,1),
(6,12,1),	(8,1,4,0),	(4,8,1),	(8,6,1),	(3,1),	(6,8,1),	(8,6,1),	(3,1),	(6,8,1),
(8,6,1),	(3,1),		(6,16,1),
(8,16,1),
(1,1,1),
]

parallel_ek=[
(3,8,4),
(8,16,4),	(8,4),	(4,16,2),
(8,16,8),	(8,2),	(6,8,1),	(6,12,3),	(9,3),	(6,12,1),
(6,12,3),	(3,1),	(3,8,1),	(4,8,1),	(3,1),	(4,8,1),	(4,8,1),	(3,1),	(4,8,1),
(4,8,1),	(3,1),	(4,4,1),	(4,8,1),	(2,1),	(4,8,1),	(4,8,1),	(2,1),	(4,8,1),	(4,8,1),	(2,1),	(4,8,1),
(4,8,1),	(2,1),	(6,8,1),	(6,12,1),	(3,1),	(6,12,1),	(6,12,1),	(3,1),	(6,12,1),
(6,12,1),	(2,1),	(4,8,1),	(8,6,1),	(1,1),	(6,8,1),	(8,6,1),	(1,1),	(6,8,1),
(8,6,1),	(1,1),	(6,16,1),
(8,16,1),
(1,1,1),
]

ifm_size = [
224,	
112,	112,	112,	
112,	112,	56,		56,		56,		56,	
56,		56,		28,		28,		28,		28,		28,		28,		28,	
28,		28,		14,		14,		14,		14,		14,		14,		14,		14,		14,		14,
14,		14,		14,		14,		14,		14,		14,		14,		14,	
14,		14,		7,		7,		7,		7,		7,		7,		7,	
7,		7,		7,	
7,		7
]

def LUT(width, depth):
	return int(width*depth/64)

def BRAM(width, depth):
	w = np.ceil(width/36)
	d = np.ceil(depth/512)
	n = int(w * d)
	e = int(width*depth/(n*512*36)*100)
	return n, e

def URAM(width, depth):
	w = np.ceil(width/72)
	d = np.ceil(depth/4096)
	n = int(w * d)
	e = int(width*depth/(n*4096*72)*100)
	return n, e

def cfm2bin(prefix):
	cfm = np.load("./blob/"+prefix+".cfm.npy").astype(np.int32)
	cfm_t = cfm.transpose(0, 2, 3, 1)
	cfm_t.tofile("./blob/"+prefix+".cfm")

def afm2bin(prefix):
	afm = np.load("./blob/"+prefix+".afm.npy").astype(np.int8)
	afm_t = afm.transpose(0, 2, 3, 1)
	afm_t.tofile("./blob/"+prefix+".afm")

def fm2bin(prefix):
	fm = np.load("./blob/"+prefix+".afm.npy").astype(np.int32)
	fm_t = fm.transpose(0, 2, 3, 1)
	fm_t.tofile("./blob/"+prefix+".fm")

def int2hex(x):
	return '\"{:#x}\"'.format(x)

def write_const(file, symbol, val):
	code = "constexpr unsigned {} = {:d};\n".format(symbol, val)
	file.write(code)
	return

def write_line(file, data, bit):
	assert len(data.shape) == 2
	data[data < 0] += np.power(2, bit)
	outer, inner = data.shape
	line = [None] * outer
	file.write("\t")
	for i in range(outer):
		cat = 0
		for j in range(inner):
			cat |= int(data[i, j]) << (bit * j)
		line[i] = cat
	file.write(", ".join(map(int2hex, line)))
	file.write(",\n")
	return

def write_arr1d(file, data, bit, prefix, sym_width, sym_dim):
	sp = data.shape
	assert len(data.shape) == 2
	if sp[0] % 8 == 0:
		data = data.reshape(sp[0] // 8, 8, sp[1])
	else:
		data = data.reshape(1, sp[0], sp[1])
	title = "const ap_uint<{0}> {1}[{2}] = {{\n".format(sym_width, prefix, sym_dim)
	file.write(title)
	for i in range(data.shape[0]):
		write_line(file, data[i], bit)
	file.write("};\n")
	return

def write_arr2d(file, data, bit, prefix, sym_width, sym_dim1, sym_dim2):
	assert len(data.shape) == 3
	title = "const ap_uint<{0}> {1}_W[{2}][{3}] = {{\n".format(sym_width, prefix, sym_dim1, sym_dim2)
	file.write(title)
	for i in range(data.shape[0]):
		write_line(file, data[i], bit)
	file.write("};\n")
	return

def write_arr3d(file, data, bit, prefix, sym_width, sym_dim1, sym_dim2, sym_dim3):
	assert len(data.shape) == 4
	title = "const ap_uint<{0}> {1}_W[{2}][{3}][{4}] = {{\n".format(sym_width, prefix, sym_dim1, sym_dim2, sym_dim3)
	file.write(title)
	for i in range(data.shape[0]):
		for j in range(data.shape[1]):
			write_line(file, data[i][j], bit)
	file.write("};\n")
	return

def cfm2bin(prefix):
	cfm = np.load("./blob/"+prefix+".cfm.npy").astype(np.int32)
	cfm_t = cfm.transpose(0, 2, 3, 1)
	cfm_t.tofile("./blob/"+prefix+".cfm")

def afm2bin(prefix):
	afm = np.load("./blob/"+prefix+".afm.npy").astype(np.int8)
	afm_t = afm.transpose(0, 2, 3, 1)
	afm_t.tofile("./blob/"+prefix+".afm")

def int2hex(x):
	return '\"{:#x}\"'.format(x)

def write_const(file, symbol, val):
	code = "constexpr unsigned {} = {:d};\n".format(symbol, val)
	file.write(code)
	return

def write_line(file, data, bit):
	assert len(data.shape) == 2
	data[data < 0] += np.power(2, bit)
	outer, inner = data.shape
	line = [None] * outer
	file.write("\t")
	for i in range(outer):
		cat = 0
		for j in range(inner):
			cat |= int(data[i, j]) << (bit * j)
		line[i] = cat
	file.write(", ".join(map(int2hex, line)))
	file.write(",\n")
	return

def write_arr1d(file, data, bit, prefix, sym_width, sym_dim):
	sp = data.shape
	assert len(data.shape) == 2
	if sp[0] % 8 == 0:
		data = data.reshape(sp[0] // 8, 8, sp[1])
	else:
		data = data.reshape(1, sp[0], sp[1])
	title = "const ap_uint<{0}> {1}[{2}] = {{\n".format(sym_width, prefix, sym_dim)
	file.write(title)
	for i in range(data.shape[0]):
		write_line(file, data[i], bit)
	file.write("};\n")
	return

def write_arr2d(file, data, bit, prefix, sym_width, sym_dim1, sym_dim2):
	assert len(data.shape) == 3
	title = "const ap_uint<{0}> {1}_W[{2}][{3}] = {{\n".format(sym_width, prefix, sym_dim1, sym_dim2)
	file.write(title)
	for i in range(data.shape[0]):
		write_line(file, data[i], bit)
	file.write("};\n")
	return

def write_arr3d(file, data, bit, prefix, sym_width, sym_dim1, sym_dim2, sym_dim3):
	assert len(data.shape) == 4
	title = "const ap_uint<{0}> {1}_W[{2}][{3}][{4}] = {{\n".format(sym_width, prefix, sym_dim1, sym_dim2, sym_dim3)
	file.write(title)
	for i in range(data.shape[0]):
		for j in range(data.shape[1]):
			write_line(file, data[i][j], bit)
	file.write("};\n")
	return

def write_dwt(file, prefix, n_io, n_act):

	wt = np.load("./blob/"+prefix+".wt.npy").astype(np.int32)
	n_ch = wt.shape[0]
	k = wt.shape[2] * wt.shape[3]

	wt_t = wt.reshape(n_ch // n_io, n_io, k)
	wt_t = wt_t.transpose(0, 2, 1) #(n_ch // n_io, k, n_io)

	sym_nch = "{}_NCH".format(prefix)
	sym_nio =  "{}_NIO".format(prefix)
	sym_act = "{}_NACT".format(prefix)
	sym_k   = "{}_K".format(prefix)
	write_const(file, sym_nch, n_ch)
	write_const(file, sym_nio, n_io)
	write_const(file, sym_act, n_act)
	write_const(file, sym_k, wt.shape[2])

	sym_width = "{} * {}".format(sym_nio, sym_bitw)
	sym_dim1 = "{} / {}".format(sym_nch, sym_nio)
	sym_dim2 = "{} * {}".format(sym_k, sym_k)
	write_arr2d(file, wt_t, bitw, prefix, sym_width, sym_dim1, sym_dim2)
	
	bias = np.load("./blob/"+prefix+".bs.npy").astype(np.int32)
	bias = bias.reshape(n_ch // n_act, n_act)
	sym_arr = "{}_B".format(prefix)
	sym_width = "{} * {}".format(sym_act, sym_bitb)
	sym_dim = "{} / {}".format(sym_nch, sym_act)
	write_arr1d(file, bias, bitb, sym_arr, sym_width, sym_dim)
	mult = np.load("./blob/"+prefix+".m.npy").astype(np.int32)
	mult = mult.reshape(n_ch // n_act, n_act)
	sym_arr = "{}_M".format(prefix)
	sym_width = "{} * {}".format(sym_act, sym_bitm)
	sym_dim = "{} / {}".format(sym_nch, sym_act)
	write_arr1d(file, mult, bitm, sym_arr, sym_width, sym_dim)
	file.write("\n")

	return

def write_dwt_ek(file, prefix, n_io, n_act, hw):

	wt = np.load("./blob/"+prefix+".wt.npy").astype(np.int32)
	n_ch = wt.shape[0]
	kh = wt.shape[2]
	kw = wt.shape[3]

	wt_t = wt.reshape(n_ch // n_io, n_io, kh, kw)
	wt_t = wt_t.transpose(0, 2, 3, 1) #(n_ch // n_io, kh, kw, n_io)
	wt_t = wt_t.reshape(n_ch // n_io, kh, kw*n_io)
	print("{} stream2window_{}u_{}u_{}u_{}u".format(prefix, n_io*bita, n_ch*bita, hw, hw))

	sym_nch = "{}_NCH".format(prefix)
	sym_nio =  "{}_NIO".format(prefix)
	sym_act = "{}_NACT".format(prefix)
	sym_k   = "{}_K".format(prefix)
	write_const(file, sym_nch, n_ch)
	write_const(file, sym_nio, n_io)
	write_const(file, sym_act, n_act)
	write_const(file, sym_k, wt.shape[2])

	sym_width = "{} * {} * {}".format(sym_nio, sym_k, sym_bitw)
	sym_dim1 = "{} / {}".format(sym_nch, sym_nio)
	sym_dim2 = "{}".format(sym_k)
	write_arr2d(file, wt_t, bitw, prefix, sym_width, sym_dim1, sym_dim2)
	
	bias = np.load("./blob/"+prefix+".bs.npy").astype(np.int32)
	bias = bias.reshape(n_ch // n_act, n_act)
	sym_arr = "{}_B".format(prefix)
	sym_width = "{} * {}".format(sym_act, sym_bitb)
	sym_dim = "{} / {}".format(sym_nch, sym_act)
	write_arr1d(file, bias, bitb, sym_arr, sym_width, sym_dim)
	mult = np.load("./blob/"+prefix+".m.npy").astype(np.int32)
	mult = mult.reshape(n_ch // n_act, n_act)
	sym_arr = "{}_M".format(prefix)
	sym_width = "{} * {}".format(sym_act, sym_bitm)
	sym_dim = "{} / {}".format(sym_nch, sym_act)
	write_arr1d(file, mult, bitm, sym_arr, sym_width, sym_dim)
	file.write("\n")

	return

def write_dwt_r(file, prefix, n_io, n_act, n_g):

	wt = np.load("./blob/"+prefix+".wt.npy").astype(np.int32)
	n_ch = wt.shape[0]
	k = wt.shape[2] * wt.shape[3]

	wt_t = wt.reshape(n_ch // n_io, n_io, k)
	wt_t = wt_t.transpose(0, 2, 1) #(n_ch // n_io, k, n_io)
	wt_t = wt_t.reshape(n_ch // n_io, k, n_g, n_io//n_g) #(n_ch // n_io, k, n_io)

	sym_nch = "{}_NCH".format(prefix)
	sym_nio = "{}_NIO".format(prefix)
	sym_act = "{}_NACT".format(prefix)
	sym_k   = "{}_K".format(prefix)
	sym_g	= "{}_NG".format(prefix)
	write_const(file, sym_nch, n_ch)
	write_const(file, sym_nio, n_io)
	write_const(file, sym_act, n_act)
	write_const(file, sym_k, wt.shape[2])
	write_const(file, sym_g, n_g)
	sym_width = "{} / {} * {}".format(sym_nio, sym_g, sym_bitw)
	sym_dim1 = "{} / {}".format(sym_nch, sym_nio)
	sym_dim2 = "{} * {}".format(sym_k, sym_k)
	sym_dim3 = "{}".format(sym_g)
	write_arr3d(file, wt_t, bitw, prefix, sym_width, sym_dim1, sym_dim2, sym_dim3)
	
	bias = np.load("./blob/"+prefix+".bs.npy").astype(np.int32)
	bias = bias.reshape(n_ch // n_act, n_act)
	sym_arr = "{}_B".format(prefix)
	sym_width = "{} * {}".format(sym_act, sym_bitb)
	sym_dim = "{} / {}".format(sym_nch, sym_act)
	write_arr1d(file, bias, bitb, sym_arr, sym_width, sym_dim)
	mult = np.load("./blob/"+prefix+".m.npy").astype(np.int32)
	mult = mult.reshape(n_ch // n_act, n_act)
	sym_arr = "{}_M".format(prefix)
	sym_width = "{} * {}".format(sym_act, sym_bitm)
	sym_dim = "{} / {}".format(sym_nch, sym_act)
	write_arr1d(file, mult, bitm, sym_arr, sym_width, sym_dim)
	file.write("\n")

	return

def write_pwt(file, prefix, n_i, n_o, n_act):
	wt = np.load("./blob/"+prefix+".wt.npy").astype(np.int32)
	n_och = wt.shape[0]
	n_ich = wt.shape[1]
	k = wt.shape[2] * wt.shape[3]

	assert k == 1

	wt_t = wt.reshape(n_och//n_o, n_o, n_ich//n_i, n_i)
	wt_t = wt_t.transpose(0, 2, 1, 3) #(n_och//n_o, n_ich//n_i, n_o, n_i)
	wt_t = wt_t.reshape(n_och//n_o, n_ich//n_i, n_o*n_i)

	sym_ich = "{}_NICH".format(prefix)
	sym_och = "{}_NOCH".format(prefix)
	sym_in  =  "{}_NIN".format(prefix)
	sym_out = "{}_NOUT".format(prefix)
	sym_act = "{}_NACT".format(prefix)
	write_const(file, sym_ich, n_ich)
	write_const(file, sym_och, n_och)
	write_const(file, sym_in , n_i)
	write_const(file, sym_out, n_o)
	if n_act > 0:
		write_const(file, sym_act, n_act)

	sym_width = "{} * {} * {}".format(sym_out, sym_in, sym_bitw)
	sym_dim1 = "{} / {}".format(sym_och, sym_out)
	sym_dim2 = "{} / {}".format(sym_ich, sym_in)

	write_arr2d(file, wt_t, bitw, prefix, sym_width, sym_dim1, sym_dim2)
	
	if n_act > 0:
		bias = np.load("./blob/"+prefix+".bs.npy").astype(np.int32)
		bias = bias.reshape(n_och // n_act, n_act)
		sym_arr = "{}_B".format(prefix)
		sym_width = "{} * {}".format(sym_act, sym_bitb)
		sym_dim = "{} / {}".format(sym_och, sym_act)
		write_arr1d(file, bias, bitb, sym_arr, sym_width, sym_dim)
		
		mult = np.load("./blob/"+prefix+".m.npy").astype(np.int32)
		mult = mult.reshape(n_och // n_act, n_act)
		sym_arr = "{}_M".format(prefix)
		sym_width = "{} * {}".format(sym_act, sym_bitm)
		sym_dim = "{} / {}".format(sym_och, sym_act)
		write_arr1d(file, mult, bitm, sym_arr, sym_width, sym_dim)
	file.write("\n")
	return

def write_wt(file, prefix, n_i, n_o, n_act):
	wt = np.load("./blob/"+prefix+".wt.npy").astype(np.int32)
	n_och = wt.shape[0]
	n_ich = wt.shape[1]
	k = wt.shape[2] * wt.shape[3]
	wt_t = wt.reshape(n_och//n_o, n_o, n_ich//n_i, n_i, k)
	wt_t = wt_t.transpose(0, 2, 4, 1, 3) #(n_och//n_o, n_ich//n_i, k, n_o, n_i)
	wt_t = wt_t.reshape(n_och//n_o, n_ich//n_i, k, n_o*n_i)

	sym_ich = "{}_NICH".format(prefix)
	sym_och = "{}_NOCH".format(prefix)
	sym_in  =  "{}_NIN".format(prefix)
	sym_out = "{}_NOUT".format(prefix)
	sym_k   = "{}_K".format(prefix)
	sym_act = "{}_NACT".format(prefix)

	write_const(file, sym_ich, n_ich)
	write_const(file, sym_och, n_och)
	write_const(file, sym_in , n_i)
	write_const(file, sym_out, n_o)
	write_const(file, sym_k, wt.shape[2])
	if n_act > 0:
		write_const(file, sym_act, n_act)
	sym_width = "{} * {} * {}".format(sym_out, sym_in, sym_bitw)
	sym_dim1 = "{} / {}".format(sym_och, sym_out)
	sym_dim2 = "{} / {}".format(sym_ich, sym_in)
	sym_dim3 = "{} * {}".format(sym_k, sym_k)
	write_arr3d(file, wt_t, bitw, prefix, sym_width, sym_dim1, sym_dim2, sym_dim3)

	if n_act > 0:
		bias = np.load("./blob/"+prefix+".bs.npy").astype(np.int32)
		bias = bias.reshape(n_och // n_act, n_act)
		sym_arr = "{}_B".format(prefix)
		sym_width = "{} * {}".format(sym_act, sym_bitb)
		sym_dim = "{} / {}".format(sym_och, sym_act)
		write_arr1d(file, bias, bitb, sym_arr, sym_width, sym_dim)
		
		mult = np.load("./blob/"+prefix+".m.npy").astype(np.int32)
		mult = mult.reshape(n_och // n_act, n_act)
		sym_arr = "{}_M".format(prefix)
		sym_width = "{} * {}".format(sym_act, sym_bitm)
		sym_dim = "{} / {}".format(sym_och, sym_act)
		write_arr1d(file, mult, bitm, sym_arr, sym_width, sym_dim)
	file.write("\n")
	return

def write_wt_ek(file, prefix, n_i, n_o, n_act):
	wt = np.load("./blob/"+prefix+".wt.npy").astype(np.int32)
	n_och = wt.shape[0]
	n_ich = wt.shape[1]
	kh = wt.shape[2]
	kw = wt.shape[3]
	wt_t = wt.reshape(n_och//n_o, n_o, n_ich//n_i, n_i, kh, kw)
	wt_t = wt_t.transpose(0, 2, 4, 1, 5, 3) #(n_och//n_o, n_ich//n_i, kh, n_o, kw, n_i)
	wt_t = wt_t.reshape(n_och//n_o, n_ich//n_i, kh, kw*n_o*n_i)

	sym_ich = "{}_NICH".format(prefix)
	sym_och = "{}_NOCH".format(prefix)
	sym_in  =  "{}_NIN".format(prefix)
	sym_out = "{}_NOUT".format(prefix)
	sym_k   = "{}_K".format(prefix)
	sym_act = "{}_NACT".format(prefix)

	write_const(file, sym_ich, n_ich)
	write_const(file, sym_och, n_och)
	write_const(file, sym_in , n_i)
	write_const(file, sym_out, n_o)
	write_const(file, sym_k, wt.shape[2])
	if n_act > 0:
		write_const(file, sym_act, n_act)
	sym_width = "{} * {} * {} * {}".format(sym_out, sym_in, sym_k, sym_bitw)
	sym_dim1 = "{} / {}".format(sym_och, sym_out)
	sym_dim2 = "{} / {}".format(sym_ich, sym_in)
	sym_dim3 = "{}".format(sym_k)
	write_arr3d(file, wt_t, bitw, prefix, sym_width, sym_dim1, sym_dim2, sym_dim3)

	if n_act > 0:
		bias = np.load("./blob/"+prefix+".bs.npy").astype(np.int32)
		bias = bias.reshape(n_och // n_act, n_act)
		sym_arr = "{}_B".format(prefix)
		sym_width = "{} * {}".format(sym_act, sym_bitb)
		sym_dim = "{} / {}".format(sym_och, sym_act)
		write_arr1d(file, bias, bitb, sym_arr, sym_width, sym_dim)
		
		mult = np.load("./blob/"+prefix+".m.npy").astype(np.int32)
		mult = mult.reshape(n_och // n_act, n_act)
		sym_arr = "{}_M".format(prefix)
		sym_width = "{} * {}".format(sym_act, sym_bitm)
		sym_dim = "{} / {}".format(sym_och, sym_act)
		write_arr1d(file, mult, bitm, sym_arr, sym_width, sym_dim)
	file.write("\n")
	return

afm2bin("input")
for i in range(52):
	afm2bin(prefixs[i])

afm2bin("b2n1_b2n2")
afm2bin("b3n1_b3n2")
afm2bin("b3n1_b3n2_b3n3")
afm2bin("b4n1_b4n2")
afm2bin("b4n1_b4n2_b4n3")
afm2bin("b4n1_b4n2_b4n3_b4n4")
afm2bin("b5n1_b5n2")
afm2bin("b5n1_b5n2_b5n3")
afm2bin("b6n1_b6n2_b6n3")

fm2bin("input")
for i in range(52):
	fm2bin(prefixs[i])

fm2bin("b2n1_b2n2")
fm2bin("b3n1_b3n2")
fm2bin("b3n1_b3n2_b3n3")
fm2bin("b4n1_b4n2")
fm2bin("b4n1_b4n2_b4n3")
fm2bin("b4n1_b4n2_b4n3_b4n4")
fm2bin("b5n1_b5n2")
fm2bin("b5n1_b5n2_b5n3")
fm2bin("b6n1_b6n2_b6n3")
cfm2bin("avgpool")

f = open(out_file, "w")
f.write("#pragma once\n")
f.write("#ifndef MBv2_PARA_H_\n")
f.write("#define MBv2_PARA_H_\n")
f.write("#include \"mbv2.h\"\n")

w = open("weight.txt","w")
for i in range(53):
	if(len(parallel_dwc_r[i])==2 or len(parallel_dwc_r[i])==4):
		wt = np.load("./blob/"+prefixs[i]+".wt.npy").astype(np.int32)
		n_ch = wt.shape[0]
		width = parallel_dwc_r[i][0]*bita
		depth = int(3*ifm_size[i]*n_ch/parallel_dwc_r[i][0])
		nLUT = LUT(width, depth)
		nBRAM, eBRAM = BRAM(width, depth)
		nURAM, eURAM = URAM(width, depth)
		LUT2BRAM = int(nLUT/nBRAM)
		LUT2URAM = int(nLUT/nURAM)
		BRAM2URAM = int(nBRAM/nURAM)
		print("{} linebuffer width = {}, linebuffer depth = {}, LUT = {}, BRAM = {}/{}%, URAM = {}/{}%, LUT2BRAM = {}, LUT2URAM = {}, BRAM2URAM = {}".\
				format(prefixs[i], width, depth, nLUT, nBRAM, eBRAM, nURAM, eURAM, LUT2BRAM, LUT2URAM, BRAM2URAM))
		w.write("{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n".format(prefixs[i], width, depth, nLUT, nBRAM, eBRAM, nURAM, eURAM, LUT2BRAM, LUT2URAM, BRAM2URAM))
		
		sym_ram = "{}_RAM".format(prefixs[i])
		ram_type = 0
		if(LUT2BRAM<100):
			ram_type = 0
		else:
			if(BRAM2URAM<5):
				ram_type = 1
			else:
				ram_type = 2
		write_const(f, sym_ram, ram_type)

for i in range(53):
	if(len(parallel_dwc_r[i])==3):
		wt = np.load("./blob/"+prefixs[i]+".wt.npy").astype(np.int32)
		n_och = wt.shape[0]
		n_ich = wt.shape[1]
		k = wt.shape[2] * wt.shape[3]
		n_i = parallel_dwc_r[i][0]
		n_o = parallel_dwc_r[i][1]

		width = n_i*n_o*bitw
		depth = int(n_och/n_o*n_ich/n_i)
		nLUT = LUT(width, depth)
		nBRAM, eBRAM = BRAM(width, depth)
		nURAM, eURAM = URAM(width, depth)
		LUT2BRAM = int(nLUT/nBRAM)
		LUT2URAM = int(nLUT/nURAM)
		BRAM2URAM = int(nBRAM/nURAM)
		print("{} weight width = {}, weight depth = {}, LUT = {}, BRAM = {}/{}%, URAM = {}/{}%, LUT2BRAM = {}, LUT2URAM = {}, BRAM2URAM = {}".\
				format(prefixs[i], width, depth, nLUT, nBRAM, eBRAM, nURAM, eURAM, LUT2BRAM, LUT2URAM, BRAM2URAM))
		w.write("{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n".format(prefixs[i], width, depth, nLUT, nBRAM, eBRAM, nURAM, eURAM, LUT2BRAM, LUT2URAM, BRAM2URAM))
		sym_ram = "{}_RAM".format(prefixs[i])
		ram_type = 0
		if(LUT2BRAM<100):
			ram_type = 0
		else:
			if(BRAM2URAM<5):
				ram_type = 1
			else:
				ram_type = 2
		write_const(f, sym_ram, ram_type)

write_wt_ek(f, prefixs[0], parallel_dwc_r[0][0], parallel_dwc_r[0][1], parallel_dwc_r[0][2])
for i in range(1, 53):
	if(len(parallel_dwc_r[i])==2):
		write_dwt(f, prefixs[i], parallel_dwc_r[i][0], parallel_dwc_r[i][1])
	elif(len(parallel_dwc_r[i])==3):
		write_pwt(f, prefixs[i], parallel_dwc_r[i][0], parallel_dwc_r[i][1], parallel_dwc_r[i][2])
	else:
		write_dwt_r(f, prefixs[i], parallel_dwc_r[i][0], parallel_dwc_r[i][1], parallel_dwc_r[i][2])
	print("write " + prefixs[i] + " weight ok")

f.write("#endif")
f.close()
